<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>气球任务实验</title>
    <script src="https://unpkg.com/jspsych@7.3.4"></script>
    <script src="https://unpkg.com/@jspsych/plugin-html-keyboard-response@1.1.3"></script>
    <script src="https://unpkg.com/@jspsych/plugin-html-button-response@1.1.3"></script>
    <script src="https://unpkg.com/@jspsych/plugin-instructions@1.1.4"></script>
    <script src="https://unpkg.com/@jspsych/plugin-survey-text@1.1.3"></script>
    <link href="https://unpkg.com/jspsych@7.3.4/css/jspsych.css" rel="stylesheet" type="text/css" />
    <style>
        .balloon-container {
            text-align: center;
            padding: 20px;
            font-family: Arial, sans-serif;
        }
        
        .balloon {
            font-size: 80px;
            transition: all 0.3s ease;
            margin: 20px 0;
        }
        
        .score-display {
            font-size: 24px;
            font-weight: bold;
            margin: 15px 0;
            padding: 10px;
            background-color: #f0f0f0;
            border-radius: 8px;
            display: inline-block;
            min-width: 200px;
        }
        
        .round-info {
            font-size: 18px;
            margin: 10px 0;
            color: #666;
        }
        
        .pump-info {
            font-size: 16px;
            margin: 10px 0;
            color: #333;
        }
        
        .explosion {
            color: red;
            font-size: 48px;
            font-weight: bold;
            animation: shake 0.5s;
        }
        
        .success {
            color: green;
            font-size: 24px;
            font-weight: bold;
        }
        
        @keyframes shake {
            0%, 100% { transform: translateX(0); }
            25% { transform: translateX(-5px); }
            75% { transform: translateX(5px); }
        }
        
        .jspsych-btn {
            font-size: 18px;
            padding: 12px 24px;
            margin: 10px;
            border-radius: 8px;
            border: none;
            cursor: pointer;
            transition: background-color 0.3;
        }
        
        .jspsych-btn:hover {
            opacity: 0.8;
        }
        
        .pump-btn {
            background-color: #4CAF50;
            color: white;
        }
        
        .stop-btn {
            background-color: #f44336;
            color: white;
        }
        
        /* 姓名输入界面样式 */
        .name-input-container {
            text-align: center;
            max-width: 400px;
            margin: 0 auto;
            padding: 40px 20px;
        }
        
        .name-input-container h1 {
            color: #333;
            margin-bottom: 30px;
        }
        
        .jspsych-survey-text-question {
            margin: 20px 0;
        }
        
        .jspsych-survey-text-question p {
            font-size: 18px;
            margin-bottom: 10px;
            color: #555;
        }
        
        .jspsych-survey-text {
            font-size: 16px;
            padding: 10px;
            width: 100%;
            max-width: 300px;
            border: 2px solid #ddd;
            border-radius: 5px;
            box-sizing: border-box;
        }
        
        .jspsych-survey-text:focus {
            outline: none;
            border-color: #4CAF50;
        }
        
        @media (max-width: 768px) {
            .balloon {
                font-size: 60px;
            }
            .score-display {
                font-size: 20px;
                min-width: 160px;
            }
            .jspsych-btn {
                font-size: 16px;
                padding: 10px 20px;
                display: block;
                width: 80%;
                margin: 10px auto;
            }
        }
    </style>
</head>
<body>
    <script>
        // 初始化jsPsych
        const jsPsych = initJsPsych({
            on_finish: function() {
                // 获取所有数据
                const allData = jsPsych.data.get();
                const participantName = allData.filter({trial_type: 'survey-text'}).values()[0].response.name;
                
                // 只获取关键试次的数据（决策和反馈）
                const relevantData = allData.filter({trial_type: 'decision'});
                
                // 创建简洁的数据摘要
                let summary = `<div style="max-width: 800px; margin: 20px auto; font-family: Arial, sans-serif;">
                    <h2>实验数据摘要</h2>
                    <p><strong>参与者：</strong>${participantName}</p>
                    <p><strong>最终得分：</strong>${totalScore}分</p>
                    <table style="border-collapse: collapse; width: 100%; margin-top: 20px;">
                        <thead>
                            <tr style="background-color: #f0f0f0;">
                                <th style="border: 1px solid #ddd; padding: 8px;">轮次</th>
                                <th style="border: 1px solid #ddd; padding: 8px;">充气次数</th>
                                <th style="border: 1px solid #ddd; padding: 8px;">动作</th>
                                <th style="border: 1px solid #ddd; padding: 8px;">结果</th>
                                <th style="border: 1px solid #ddd; padding: 8px;">本轮得分</th>
                            </tr>
                        </thead>
                        <tbody>`;
                
                relevantData.values().forEach((trial) => {
                    if (trial.action === 'stop' || trial.result === 'explosion' || trial.pumps_after_action >= MAX_PUMPS) {
                        const blockLabel = trial.block === 'practice' ? '练习' : `第${trial.block}轮`;
                        const resultText = trial.result === 'explosion' ? '💥爆炸' : 
                                         trial.result === 'stopped' ? '✅停止' : '✅完成';
                        const score = trial.result === 'explosion' ? 0 : trial.block_score_after_action;
                        
                        summary += `
                            <tr>
                                <td style="border: 1px solid #ddd; padding: 8px; text-align: center;">${blockLabel}</td>
                                <td style="border: 1px solid #ddd; padding: 8px; text-align: center;">${trial.pumps_after_action}</td>
                                <td style="border: 1px solid #ddd; padding: 8px; text-align: center;">${trial.action === 'stop' ? '停止' : '充气'}</td>
                                <td style="border: 1px solid #ddd; padding: 8px; text-align: center;">${resultText}</td>
                                <td style="border: 1px solid #ddd; padding: 8px; text-align: center;">${score}</td>
                            </tr>`;
                    }
                });
                
                summary += `
                        </tbody>
                    </table>
                    <div style="margin-top: 20px; padding: 15px; background-color: #f9f9f9; border-radius: 5px;">
                        <p><strong>数据已自动下载为CSV文件</strong></p>
                        <p>文件名：bart_data_${participantName}_${new Date().toLocaleDateString('zh-CN').replace(/\//g, '-')}.csv</p>
                    </div>
                </div>`;
                
                // 显示摘要
                jsPsych.data.displayData('html', summary);
                
                // 生成CSV并下载
                const csv = allData.csv();
                const fileName = `bart_data_${participantName}_${new Date().toLocaleDateString('zh-CN').replace(/\//g, '-')}.csv`;
                const dataStr = "data:text/csv;charset=utf-8,\uFEFF" + encodeURIComponent(csv);
                const downloadAnchorNode = document.createElement('a');
                downloadAnchorNode.setAttribute("href", dataStr);
                downloadAnchorNode.setAttribute("download", fileName);
                document.body.appendChild(downloadAnchorNode);
                downloadAnchorNode.click();
                downloadAnchorNode.remove();
            }
        });

        // 实验参数
        const BLOCKS = 10;
        const MAX_PUMPS = 5;
        const POINTS_PER_PUMP = 5;
        const PROBABILITIES = [0.05, 0.12, 0.20, 0.30, 0.40];

        // 全局变量
        let totalScore = 0;
        let participantName = '';

        // 姓名输入界面
        const nameInput = {
            type: jsPsychSurveyText,
            preamble: '<div class="name-input-container"><h1>欢迎参加实验</h1></div>',
            questions: [
                {
                    prompt: '请输入您的姓名：',
                    name: 'name',
                    required: true,
                    placeholder: '请在此输入姓名'
                }
            ],
            button_label: '开始实验',
            on_finish: function(data) {
                participantName = data.response.name;
                data.participant_name = participantName;
            }
        };

        // 欢迎页面
        const welcome = {
            type: jsPsychInstructions,
            pages: [
                function() {
                    return `<div class="balloon-container">
                        <h1>您好，${participantName}！</h1>
                        <h2>欢迎参加气球任务实验！</h2>
                        <p>在接下来的任务中，您将看到一系列气球。</p>
                        <p>您的任务是通过给气球充气来获得分数。</p>
                        <p>每次给气球充气，您将获得${POINTS_PER_PUMP}分。</p>
                        <p>但是，如果气球爆炸了，您将失去该轮累积的所有分数。</p>
                        <p>您可以在任何时候选择停止充气并保存当前分数。</p>
                    </div>`;
                },
                
                `<div class="balloon-container">
                    <h2>任务规则：</h2>
                    <ul style="text-align: left; display: inline-block;">
                        <li>每个气球最多可以充气${MAX_PUMPS}次</li>
                        <li>每次充气成功，您获得${POINTS_PER_PUMP}分</li>
                        <li>随着充气次数增加，气球爆炸的风险也会增加</li>
                        <li>如果选择停止充气，您将保存该轮的所有分数</li>
                        <li>如果气球爆炸，该轮分数全部清零</li>
                        <li>您可以在第一次就选择停止（但此时没有分数）</li>
                    </ul>
                    <p><strong>您的目标是获得尽可能多的总分数。</strong></p>
                    <p>总共有${BLOCKS}轮，每轮都是新的气球。</p>
                </div>`,
                
                `<div class="balloon-container">
                    <h2>现在进行一个练习轮次</h2>
                    <p>练习中的分数不计入正式成绩。</p>
                    <p><strong>操作方法：</strong></p>
                    <p>• 点击"充气"按钮给气球充气</p>
                    <p>• 点击"停止并保存"按钮结束当前轮次并保存分数</p>
                    <p>准备好了吗？</p>
                </div>`
            ],
            show_clickable_nav: true,
            button_label_previous: '上一页',
            button_label_next: '下一页'
        };

        // 创建单个轮次 - 使用循环函数而不是预先创建所有试次
        function createBalloonRound(isPractice = false, blockNumber = 1) {
            let pumps = 0;
            let blockScore = 0;
            let roundComplete = false;
            
            const balloonTrial = {
                timeline: [
                    // 决策试次
                    {
                        type: jsPsychHtmlButtonResponse,
                        stimulus: function() {
                            const blockLabel = isPractice ? '练习轮次' : `第${blockNumber}轮/共${BLOCKS}轮`;
                            const balloonSize = Math.min(80 + pumps * 15, 140);
                            const balloonColor = pumps <= 1 ? '🔴' : pumps <= 3 ? '🟠' : '🟡';
                            
                            return `
                                <div class="balloon-container">
                                    <div class="score-display">总分：${totalScore}分</div>
                                    <div style="font-size: ${balloonSize}px;" class="balloon">${balloonColor}</div>
                                    <div class="pump-info">当前轮次分数：${blockScore}分</div>
                                    <div class="pump-info">充气次数：${pumps}/${MAX_PUMPS}</div>
                                    <div class="round-info">${blockLabel}</div>
                                </div>
                            `;
                        },
                        choices: ['充气', '停止并保存'],
                        button_html: '<button class="jspsych-btn %choice%">%choice%</button>',
                        on_finish: function(data) {
                            data.participant_name = participantName;
                            data.block = isPractice ? 'practice' : blockNumber;
                            data.pumps_before_action = pumps;
                            data.block_score_before_action = blockScore;
                            data.total_score = totalScore;
                            data.is_practice = isPractice;
                            data.trial_type = 'decision';
                            
                            if (data.response == 0) { // 充气
                                pumps++;
                                const explosionProb = PROBABILITIES[pumps - 1];
                                const exploded = Math.random() < explosionProb;
                                
                                data.action = 'pump';
                                data.explosion_probability = explosionProb;
                                data.exploded = exploded;
                                
                                if (exploded) {
                                    blockScore = 0;
                                    data.result = 'explosion';
                                    roundComplete = true;
                                } else {
                                    blockScore += POINTS_PER_PUMP;
                                    data.result = 'success';
                                    // 检查是否达到最大充气次数
                                    if (pumps >= MAX_PUMPS) {
                                        if (!isPractice) {
                                            totalScore += blockScore;
                                        }
                                        roundComplete = true;
                                    }
                                }
                            } else { // 停止
                                data.action = 'stop';
                                data.result = 'stopped';
                                if (!isPractice) {
                                    totalScore += blockScore;
                                }
                                roundComplete = true;
                            }
                            
                            data.pumps_after_action = pumps;
                            data.block_score_after_action = blockScore;
                            data.final_total_score = totalScore;
                        }
                    },
                    // 反馈试次
                    {
                        type: jsPsychHtmlButtonResponse,
                        stimulus: function() {
                            const lastData = jsPsych.data.get().last(1).values()[0];
                            const blockLabel = isPractice ? '练习轮次' : `第${blockNumber}轮/共${BLOCKS}轮`;
                            
                            if (lastData.action === 'pump' && lastData.exploded) {
                                // 爆炸反馈
                                return `
                                    <div class="balloon-container">
                                        <div class="score-display">总分：${totalScore}分</div>
                                        <div class="explosion">💥 爆炸！</div>
                                        <div class="explosion">本轮0分</div>
                                        <div class="round-info">${blockLabel}</div>
                                    </div>
                                `;
                            } else if (lastData.action === 'pump' && !lastData.exploded) {
                                // 充气成功反馈
                                if (pumps >= MAX_PUMPS) {
                                    return `
                                        <div class="balloon-container">
                                            <div class="score-display">总分：${totalScore}分</div>
                                            <div class="success">达到最大充气次数！</div>
                                            <div class="success">本轮获得：${blockScore}分</div>
                                            <div class="round-info">${blockLabel}</div>
                                        </div>
                                    `;
                                } else {
                                    // 普通充气成功反馈
                                    const balloonSize = Math.min(80 + pumps * 15, 140);
                                    const balloonColor = pumps <= 1 ? '🔴' : pumps <= 3 ? '🟠' : '🟡';
                                    return `
                                        <div class="balloon-container">
                                            <div class="score-display">总分：${totalScore}分</div>
                                            <div class="success">+${POINTS_PER_PUMP}分！</div>
                                            <div style="font-size: ${balloonSize}px;" class="balloon">${balloonColor}</div>
                                            <div class="pump-info">当前轮次分数：${blockScore}分</div>
                                            <div class="pump-info">充气次数：${pumps}/${MAX_PUMPS}</div>
                                            <div class="round-info">${blockLabel}</div>
                                        </div>
                                    `;
                                }
                            } else if (lastData.action === 'stop') {
                                // 停止反馈
                                return `
                                    <div class="balloon-container">
                                        <div class="score-display">总分：${totalScore}分</div>
                                        <div class="success">${blockScore > 0 ? '保存成功！' : '您选择了停止'}</div>
                                        <div class="success">本轮获得：${blockScore}分</div>
                                        <div class="round-info">${blockLabel}</div>
                                    </div>
                                `;
                            }
                        },
                        choices: function() {
                            // 只有在轮次结束时才显示"继续"按钮
                            if (roundComplete) {
                                return ['继续'];
                            } else {
                                return [];
                            }
                        },
                        trial_duration: function() {
                            // 轮次结束等待点击，否则800毫秒后自动继续
                            return roundComplete ? null : 800;
                        },
                        button_html: '<button class="jspsych-btn">%choice%</button>',
                        on_finish: function(data) {
                            data.participant_name = participantName;
                            data.trial_type = 'feedback';
                            data.block = isPractice ? 'practice' : blockNumber;
                            data.is_practice = isPractice;
                        }
                    }
                ],
                loop_function: function() {
                    // 继续循环直到轮次结束
                    return !roundComplete;
                }
            };
            
            return balloonTrial;
        }

        // 创建时间线
        let timeline = [];
        
        // 添加姓名输入
        timeline.push(nameInput);
        
        // 添加欢迎和指导
        timeline.push(welcome);
        
        // 添加练习轮次
        timeline.push(createBalloonRound(true));
        
        // 练习结束
        const practiceEnd = {
            type: jsPsychHtmlButtonResponse,
            stimulus: `
                <div class="balloon-container">
                    <h2>练习完成！</h2>
                    <p>您已经熟悉了任务流程。</p>
                    <p>现在开始正式任务，共有${BLOCKS}轮。</p>
                    <p>记住：目标是获得尽可能多的总分数！</p>
                </div>
            `,
            choices: ['开始正式任务'],
            button_html: '<button class="jspsych-btn">%choice%</button>',
            on_start: function() {
                // 重置变量为正式任务准备
                totalScore = 0;
            },
            on_finish: function(data) {
                data.participant_name = participantName;
            }
        };
        timeline.push(practiceEnd);
        
        // 添加正式任务轮次
        for (let i = 0; i < BLOCKS; i++) {
            const currentBlock = i + 1;
            
            // 轮次开始提示（第一轮不需要）
            if (i > 0) {
                const roundStart = {
                    type: jsPsychHtmlButtonResponse,
                    stimulus: function() {
                        return `
                            <div class="balloon-container">
                                <h2>第 ${currentBlock} 轮</h2>
                                <div class="score-display">当前总分：${totalScore}分</div>
                                <p>准备开始...</p>
                            </div>
                        `;
                    },
                    choices: ['开始'],
                    trial_duration: null,
                    button_html: '<button class="jspsych-btn">%choice%</button>'
                };
                timeline.push(roundStart);
            }
            
            // 气球轮次
            timeline.push(createBalloonRound(false, currentBlock));
            
            // 中场休息（第5轮后）
            if (i === 4) {
                const midBreak = {
                    type: jsPsychHtmlButtonResponse,
                    stimulus: function() {
                        return `
                            <div class="balloon-container">
                                <h2>您已完成5轮任务</h2>
                                <div class="score-display">当前总分：${totalScore}分</div>
                                <p>请稍作休息，点击"继续"进行后续任务</p>
                                <p>剩余5轮</p>
                            </div>
                        `;
                    },
                    choices: ['继续'],
                    button_html: '<button class="jspsych-btn">%choice%</button>'
                };
                timeline.push(midBreak);
            }
        }
        
        // 实验结束
        const endExperiment = {
            type: jsPsychHtmlButtonResponse,
            stimulus: function() {
                return `
                    <div class="balloon-container">
                        <h1>实验完成！</h1>
                        <h2>${participantName}，感谢您的参与！</h2>
                        <div class="score-display">您的最终成绩：${totalScore}分</div>
                        <p>您的数据将在下一页显示，请保存或截图。</p>
                    </div>
                `;
            },
            choices: ['查看数据'],
            button_html: '<button class="jspsych-btn">%choice%</button>'
        };
        timeline.push(endExperiment);
        
        // 运行实验
        jsPsych.run(timeline);
    </script>
</body>
</html>